/*
*/

package rosas.lou.weatherclasses;

import java.util.*;
import java.lang.*;
import rosas.lou.weatherclasses.*;
import gnu.io.*;

import com.dalsemi.onewire.*;
import com.dalsemi.onewire.adapter.*;
import com.dalsemi.onewire.container.*;

public class IButton{
   private MissionLog missionLog;
   private String name;
   private String address;
   private double heatIndex = -99.9;
   private double dewPoint  = -99.9;
   //Put listeners in a list to handle multiple listeners
   private List<MemoryListener> ml_List   = null;
   private List<MissionListener> mis_List = null;
   
   //*********************Public Methods***************************
   /*
   */
   public IButton(){
      this.findSensors();
   }
   
   /*
   */
   public IButton(String name, String address){
      this.setName(name);
      this.setAddress(address);
      this.setUpMissionLog();
   }
   
   /*
   Register a Memory Listener
   */
   public void addMemoryListener(MemoryListener ml){
      try{
         this.ml_List.add(ml);
      }
      catch(NullPointerException npe){
         //Save the data off in a Vector
         this.ml_List = new Vector<MemoryListener>();
         this.ml_List.add(ml);
      }
   }
   
   /*
   Register a Mission Listener
   */
   public void addMissionListener(MissionListener ml){
      try{
         this.mis_List.add(ml);
      }
      catch(NullPointerException npe){
         this.mis_List = new Vector<MissionListener>();
         this.mis_List.add(ml);
      }
   }
   
   /*
   */
   public void clearMemory(){
      String memoryEventString = new String();
      try{
         this.missionLog.clearLog();
         memoryEventString = new String("Memory Cleared ");
         memoryEventString = memoryEventString.concat("on iButton");
         memoryEventString = memoryEventString.concat(" device");
      }
      catch(MemoryException me){
         memoryEventString = new String(me.getMessage());
      }
      catch(NullPointerException npe){
         npe.printStackTrace();
         memoryEventString = new String(npe.getMessage());
      }
      finally{
         this.publishMemoryEvent(memoryEventString);
      }
   }
   
   /*
   */
   public String getAddress(){
      return this.address;
   }
   
   /*
   */
   public MissionLog getMissionLog(){
      return this.missionLog;
   }
   
   /*
   */
   public String getName(){
      return this.name;
   }
   
   
   /*
   */
   public void startMission(){
      this.startMission(MissionLog.DEFAULT_LOGGING_RATE);
   }
   
   /*
   */
   public void startMission(int sampleRate){
      String missionEventString = new String();
      try{
         //Get the Mission Log (better way of doing this, I feel)
         MissionLog ml = this.getMissionLog();
         ml.startLogging(sampleRate);
         missionEventString = new String("Mission Started on ");
         missionEventString = missionEventString.concat("iButton");
         missionEventString = missionEventString.concat(" device");
      }
      catch(MissionException me){
         missionEventString = new String(me.getMessage());
      }
      catch(NullPointerException npe){
         missionEventString = new String(npe.getMessage());
      }
      finally{
         this.publishMissionEvent(missionEventString);
      }
   }
   
   /*
   */
   public void stopMission(){
      String missionEventString = new String();
      try{
         this.missionLog.stopLogging();
         missionEventString = new String("Mission Stopped on ");
         missionEventString = missionEventString.concat("iButton");
         missionEventString = missionEventString.concat(" device");
      }
      catch(MissionException me){
         missionEventString = new String(me.getMessage());
      }
      catch(NullPointerException npe){
         missionEventString = new String(npe.getMessage());
      }
      finally{
         this.publishMissionEvent(missionEventString);
      }
   }
   
   /*
   Override the toString() method from the Object Class
   */
   public String toString(){
      
      return new String(this.getName()+", "+this.getAddress());
   }
   
   //**********************Private Methods*************************
   /*
   */
   private void findSensors(){
      PortSniffer ps = new PortSniffer(PortSniffer.PORT_USB);
      Hashtable hash = ps.findPorts();
      Enumeration<String> ports = hash.keys();
      /*Finding this sensor is more "specialized" than finding
      the weather sensors-->because there truthfully ONLY
      one Sensor:  the iButton, which I can get BOTH the
      stored temperature and humidity data.*/
      while(ports.hasMoreElements()){
         //Get the next Key in the Hashtable
         String port = (String)ports.nextElement();
         //Now, get the name and address of the sensor:
         //port is the key into the Hashtable
         Stack<String> sensorData = (Stack)hash.get(port);
         Enumeration<String> element = sensorData.elements();
         while(element.hasMoreElements()){
            String name    = element.nextElement();
            String address = element.nextElement();
            if(!name.equals("DS1990A")){
               /*Since this is a Thermochron iButton, I should only
               have one name and address (asside from the adapter
               address*/
               this.setName(name);
               this.setAddress(address);
            }
         }
      }
      this.setUpMissionLog();
   }
   
   /*
   */
   private void publishMemoryEvent(String eventString){
      MemoryEvent evt = new MemoryEvent(this, eventString);
      try{
         Iterator<MemoryListener> i = this.ml_List.iterator();
         while(i.hasNext()){
            (i.next()).onMemoryEvent(evt);
         }
      }
      //If the exception occurs, there are no memory listeners,
      //regardless, so the only thing to do is aleart through
      //the "typical channels"
      catch(NullPointerException npe){
         npe.printStackTrace();
      }
   }
   
   /*
   */
   private void publishMissionEvent(String eventString){
      MissionEvent evt = new MissionEvent(this, eventString);
      try{
         Iterator<MissionListener> i = this.mis_List.iterator();
         while(i.hasNext()){
            (i.next()).onMissionEvent(evt);
         }
      }
      //If the exception occurs, there are no Mission listeners,
      //regardless, so the only thing to do is aleart through
      //the "typical channels"      
      catch(NullPointerException npe){
         npe.printStackTrace();
      }
   }
   
   /*
   */
   private void setAddress(String address){
      this.address = new String(address);
   }
   
   /*
   */
   private void setName(String name){
      this.name = new String(name);
   }
   
   /*
   */
   private void setUpMissionLog(){
      DSPortAdapter dspa = null;
      try{
         dspa = OneWireAccessProvider.getDefaultAdapter();
         this.missionLog = new MissionLog(new OneWireContainer41(
                                          dspa, this.getAddress()));
      }
      catch(OneWireIOException ioe){
         ioe.printStackTrace();
      }
      catch(OneWireException owe){
         owe.printStackTrace();
      }
   }

}